﻿using Microsoft.Xna.Framework;
using System;
using System.Linq;
using Terraria;
using Terraria.DataStructures;
using Terraria.GameInput;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using WorseGame.Common.Configs;

namespace WorseGame.Common.Players
{
    public class WorsePlayer : ModPlayer
    {
        private bool usedRecallItem = false;
        public LocalizedText DeathMessage;
        private const float SelfHarmChance = 0.05f;
        private int slot = 1;
        public override bool CanUseItem(Item item)
        {
            if (ProjectileConfig.Instance.MinionsDisappear)
            {
                if (IsRecallItem(item))
                {
                    usedRecallItem = true;
                }
            }
            return base.CanUseItem(item);
        }
        private static bool IsRecallItem(Item item)
        {
            int[] recallItems = [ItemID.MagicMirror, ItemID.IceMirror, ItemID.CellPhone, ItemID.RecallPotion, ItemID.Shellphone, ItemID.ShellphoneSpawn, ItemID.ShellphoneOcean, ItemID.ShellphoneHell, ItemID.PotionOfReturn,];
            return recallItems.Contains(item.type);
        }
        public override void PostUpdate()
        {
            if (ProjectileConfig.Instance.MinionsDisappear)
            {
                if (usedRecallItem)
                {
                    usedRecallItem = false;
                    DespawnMinionsOnRecall();
                }
            }
            if (ItemConfig.Instance.SelfHarmOnWeaponUse)
            {
                if (Player.controlUseItem)
                {
                    float chance = Main.rand.NextFloat();
                    if (chance <= SelfHarmChance)
                    {
                        int damage = (int)(Player.HeldItem.damage * 0.3f);
                        Player.Hurt(PlayerDeathReason.ByCustomReason(DeathMessage.ToNetworkText(Player.name)), damage, 0);
                    }
                }
            }
            if (PlayerConfig.Instance.HighLightSleep)
            {
                if (Player.sleeping.isSleeping)
                {
                    Point bedTilePos = Player.Bottom.ToTileCoordinates();
                    if (HasLightSourcesNearBed(bedTilePos.X, bedTilePos.Y))
                    {
                        Player.sleeping.StopSleeping(Player);
                        if (Main.myPlayer == Player.whoAmI)
                        {
                            Main.NewText(Language.GetTextValue("Mods.WorseGame.NewText.Sleep"), Color.Orange);
                        }
                    }
                }
            }
            if (PlayerConfig.Instance.MorePeopleDontSleep)
            {
                if (Player.sleeping.isSleeping)
                {
                    Point bedTilePos = Player.Bottom.ToTileCoordinates();
                    int entityCount = CountEntitiesNearBed(bedTilePos.X, bedTilePos.Y);
                    if (entityCount >= 3)
                    {
                        Player.sleeping.StopSleeping(Player);
                        if (Main.myPlayer == Player.whoAmI)
                        {
                            Main.NewText(Language.GetTextValue("Mods.WorseGame.NewText.Sleep1"), Color.Orange);
                        }
                    }
                }
            }
            if (PlayerConfig.Instance.ToManyMinionDontSleep)
            {
                if (Player.sleeping.isSleeping)
                {
                    Point bedTilePos = Player.Bottom.ToTileCoordinates();
                    int minionCount = CountMinionsNearBed(bedTilePos.X, bedTilePos.Y);
                    if (minionCount >= 3)
                    {
                        Player.sleeping.StopSleeping(Player);
                        if (Main.myPlayer == Player.whoAmI)
                        {
                            Main.NewText(Language.GetTextValue("Mods.WorseGame.NewText.Sleep2"), Color.Orange);
                        }
                    }
                }
            }
            if (PlayerConfig.Instance.ToManyMonstersDontSleep)
            {
                if (Player.sleeping.isSleeping)
                {
                    Point bedTilePos = Player.Bottom.ToTileCoordinates();
                    int entityCount = CountEntitiesNearBed1(bedTilePos.X, bedTilePos.Y);
                    if (entityCount >= 3)
                    {
                        Player.sleeping.StopSleeping(Player);
                        if (Main.myPlayer == Player.whoAmI)
                        {
                            Main.NewText(Language.GetTextValue("Mods.WorseGame.NewText.Sleep3"), Color.Orange);
                        }
                    }
                }
            }
        }
        private int CountMinionsNearBed(int tileX, int tileY)
        {
            int count = 0;
            Rectangle bedArea = new(tileX * 16 - 160, tileY * 16 - 160, 320, 320);
            for (int i = 0; i < Main.maxProjectiles; i++)
            {
                Projectile proj = Main.projectile[i];
                if (proj.active && proj.owner == Player.whoAmI && (proj.minion || proj.sentry || proj.minionSlots > 0))
                {
                    if (bedArea.Intersects(proj.getRect()))
                    {
                        count++;
                    }
                }
            }
            return count;
        }
        private static int CountEntitiesNearBed1(int tileX, int tileY)
        {
            int count = 0;
            Rectangle bedArea = new(tileX * 16 - 160, tileY * 16 - 160, 320, 320);
            for (int i = 0; i < Main.maxNPCs; i++)
            {
                NPC npc = Main.npc[i];
                if (npc.active && !npc.friendly)
                {
                    if (bedArea.Intersects(npc.getRect()))
                    {
                        count++;
                    }
                }
            }
            return count;
        }
        private int CountEntitiesNearBed(int tileX, int tileY)
        {
            int count = 0;
            Rectangle bedArea = new(tileX * 16 - 160, tileY * 16 - 160, 320, 320);
            for (int i = 0; i < Main.maxPlayers; i++)
            {
                if (i != Player.whoAmI && Main.player[i].active && !Main.player[i].dead)
                {
                    if (bedArea.Intersects(Main.player[i].getRect()))
                    {
                        count++;
                    }
                }
            }
            for (int i = 0; i < Main.maxNPCs; i++)
            {
                NPC npc = Main.npc[i];
                if (npc.active && npc.townNPC)
                {
                    if (bedArea.Intersects(npc.getRect()))
                    {
                        count++;
                    }
                }
            }
            return count;
        }
        private static bool HasLightSourcesNearBed(int tileX, int tileY)
        {
            for (int x = tileX - 3; x <= tileX + 3; x++)
            {
                for (int y = tileY - 3; y <= tileY + 3; y++)
                {
                    if (WorldGen.InWorld(x, y))
                    {
                        Tile tile = Main.tile[x, y];
                        if (tile != null && tile.HasTile)
                        {
                            if (IsLightSourceTile(tile.TileType))
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }
        private static bool IsLightSourceTile(int tileType)
        {
            return tileType == TileID.Torches || tileType == TileID.Campfire || tileType == TileID.Candelabras || tileType == TileID.Lamps || tileType == TileID.Chandeliers || tileType == TileID.Candles || tileType == TileID.LavaMoss || tileType == TileID.WaterCandle || tileType == TileID.PeaceCandle || tileType == TileID.ShimmerflyinaBottle || tileType == TileID.FireflyinaBottle;
        }
        private static bool IsSummonProjectile(Projectile proj)
        {
            return proj.minion || proj.sentry || proj.minionSlots > 0;
        }
        private void DespawnMinionsOnRecall()
        {
            int despawnCount = 0;
            for (int i = 0; i < Main.maxProjectiles; i++)
            {
                Projectile proj = Main.projectile[i];
                if (proj.active && proj.owner == Player.whoAmI && IsSummonProjectile(proj))
                {
                    proj.Kill();
                    despawnCount++;
                }
            }
            if (despawnCount > 0 && Main.netMode != NetmodeID.Server)
            {
                Main.NewText(Language.GetTextValue("Mods.WorseGame.NewText.Minion1") + $"{despawnCount}" + Language.GetTextValue("Mods.WorseGame.NewText.Minion2"), Color.LightBlue);
                Terraria.Audio.SoundEngine.PlaySound(SoundID.Item8 with { Pitch = -0.2f }, Player.Center);
            }
        }
        public override void ResetEffects()
        {
            if (PlayerConfig.Instance.Defensehalved)
            {
                Player.statDefense /= 2;
            }
            if (PlayerConfig.Instance.HalvesMPHP)
            {
                Player.statManaMax2 /= 2;
                Player.statLifeMax2 /= 2;
            }
        }
        public override void CatchFish(FishingAttempt attempt, ref int itemDrop, ref int npcSpawn, ref AdvancedPopupRequest sonar, ref Vector2 sonarPosition)
        {
            if (PlayerConfig.Instance.QuestFishDisappeared)
            {
                if (itemDrop == Main.anglerQuestItemNetIDs[Main.anglerQuest])
                {
                    if (Main.rand.NextFloat() < 0.5f)
                    {
                        itemDrop = ItemID.None;
                        Main.AnglerQuestSwap();
                        Main.NewText(Language.GetTextValue("Mods.WorseGame.NewText.Fish"), 255, 100, 100);
                    }
                }
            }
        }
        public override void PostUpdateBuffs()
        {
            if (MultiplayerModeConfig.Instance.SharedBuff)
            {
                for (int i = 0; i < Main.CurrentFrameFlags.ActivePlayersCount; i++)
                {
                    for (int j = 0; j < BuffLoader.BuffCount; j++)
                    {
                        if (Player.HasBuff(j) && !Main.player[i].HasBuff(j))
                        {
                            Main.player[i].AddBuff(j, 300, true);
                        }
                    }
                }
            }
        }
        public override void OnRespawn()
        {
            if (PlayerConfig.Instance.InitialHP)
            {
                Player.statLife = 1;
            }
        }
        public override void ProcessTriggers(TriggersSet triggersSet)
        {
            if (BugConfig.Instance.FlyingMountGravity)
            {
                if (triggersSet.Up && Player.gravDir != -1f && Player.mount.Active)
                {
                    Player.mount.Dismount(Player);
                }
            }

            if (PlayerConfig.Instance.SmartCursor)
            {
                if (Main.mouseRight)
                {
                    if (Main.rand.NextFloat() < 0.15f)
                    {
                        Player.controlSmart = true;
                    }
                }
            }
            if (ItemConfig.Instance.Itemmovement)
            {
                if (Player.whoAmI == Main.myPlayer)
                {
                    slot++;
                    if (slot > 4)
                    {
                        slot = 1;
                    }
                    for (int i = 0; i < 10; i++)
                    {
                        (Player.inventory[i], Player.inventory[slot * 10 + i]) = (Player.inventory[slot * 10 + i], Player.inventory[i]);
                        if (Main.netMode == NetmodeID.Server)
                        {
                            NetMessage.SendData(MessageID.SyncEquipment, -1, -1, null, Main.myPlayer, i, Main.player[Main.myPlayer].inventory[i].prefix, 0f, 0, 0, 0);
                            NetMessage.SendData(MessageID.SyncEquipment, -1, -1, null, Main.myPlayer, slot * 10 + i, Main.player[Main.myPlayer].inventory[slot * 10 + i].prefix, 0f, 0, 0, 0);
                        }
                    }
                    for (int i = 0; i < 10; i++)
                    {
                        int pos = Main.rand.Next(10, 50);
                        Item item = Player.inventory[pos];
                        Item item1 = Player.inventory[i];
                        Player.inventory[i] = item;
                        Player.inventory[pos] = item1;
                    }
                }
            }
        }



        public override void PreUpdate()
        {
            if (PlayerConfig.Instance.Breathingtime)
            {
                Player.breathMax = 30;
            }
        }
        public override void Kill(double damage, int hitDirection, bool pvp, PlayerDeathReason damageSource)
        {
            if (PlayerConfig.Instance.Respawntimedoubled)
            {
                Player.respawnTimer = 3600;
            }
            if (MultiplayerModeConfig.Instance.DeathLink)
            {
                if (Main.netMode != NetmodeID.Server)
                {
                    foreach (var target in Main.player)
                    {
                        if (target.active && !target.dead)
                        {
                            if (target.whoAmI != Player.whoAmI)
                            {
                                if (target.whoAmI == Main.myPlayer)
                                {
                                    target.KillMe(PlayerDeathReason.ByCustomReason(DeathMessage.ToNetworkText(Player.name)), 228, 0, false);
                                }
                            }
                        }
                    }
                }
            }
        }
        public override void PostUpdateEquips()
        {
            if (PlayerConfig.Instance.Wingflighttimehalved)
            {
                if (Player.wings > 0)
                {
                    Player.wingTimeMax /= 2;
                }
            }
        }
    }
}
